package com.manli.api.service.wechat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.manli.api.base.exception.MyException;
import com.manli.api.base.redis.scenes.delayjob.Message;
import com.manli.api.base.redis.scenes.delayjob.RedisTaskUtil;
import com.manli.api.base.redis.scenes.delayjob.RedisZSetDelayedQueue;
import com.manli.api.dao.*;
import com.manli.api.dao.wechat.WeChatUserInfoDao;
import com.manli.api.dto.*;
import com.manli.api.enums.QueueNameEnums;
import com.manli.api.enums.ResultEnums;
import com.manli.api.enums.SourceSubEnums;
import com.manli.api.pojo.*;
import com.manli.api.pojo.dingdanxia.*;
import com.manli.api.util.*;
import com.manli.common.utils.HttpUtil;
import com.manli.common.utils.RandomUtils;
import com.manli.common.utils.StringUtil;
import com.manli.common.utils.WeChatSignUtils;
import com.manli.wechat.pojo.WeChatUserInfo;
import com.manli.wechat.utils.wxpay.WxPayPojoV2;
import com.manli.wechat.utils.wxpay.config.MyWxPayConfig;
import com.manli.wechat.utils.wxpay.sdk.AESUtil;
import com.manli.wechat.utils.wxpay.sdk.WXPay;
import com.manli.wechat.utils.wxpay.sdk.WXPayConstants;
import com.manli.wechat.utils.wxpay.sdk.WXPayUtil;
import com.manli.wechat.utils.wxpayv3.pojo.*;
import com.manli.wechat.utils.wxpayv3.wxsdk.WxpayV3Utils;
import org.apache.commons.lang3.StringUtils;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.engine.PageQuery;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.stream.Collectors;

@Service
@Transactional
public class WechatPayService {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private SQLManager sqlManager;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    SessionInfoUtils sessionInfoUtils;

    @Autowired
    OrderInfoDao orderInfoDao;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedisTaskUtil redisTaskUtil;

    @Autowired
    WechatShopService wechatShopService;

    @Autowired
    ActivityGoodsDao activityGoodsDao;

    @Autowired
    BuyCarLogDao buyCarLogDao;

    @Autowired
    OrderRefuseApplyDao orderRefuseApplyDao;

    @Autowired
    ViewOrderGoodsDao viewOrderGoodsDao;

    @Autowired
    WeChatUserInfoAddressDao weChatUserInfoAddressDao;

    @Autowired
    VisitWantToBuyLogDao visitWantToBuyLogDao;

    @Autowired
    BranchDao branchDao;

    @Autowired
    PartnerDao partnerDao;

    @Autowired
    GoodsDefDao goodsDefDao;
    @Autowired
    WechatActivationCouponBatchDao wechatActivationCouponBatchDao;
    @Autowired
    DingDanXiaUtils dingDanXiaUtils;
    @Autowired
    MajorTypeDao majorTypeDao;
    @Autowired
    WechatUserGetCouponLogDao wechatUserGetCouponLogDao;
    @Autowired
    WeChatUserInfoDao weChatUserInfoDao;
    //订单侠接口apikey
    private static String dingdanxiaKey = "DcfeAj4wyZ875h32YYggeWr1kODgSbf1";

    @Value("${wechatpay.certPath}")
    String certPath ;
    //漫狸科技（温州）服务商appid
    String appID = "wx6f56d14c68184b2f";
    //漫狸科技（温州） 漫淘淘小程序
    String appIdMiniprogram = "wx68b41af749849d4e";
    //漫狸科技（温州） 服务商商户号
    String mchID = "1601420795";
    String key = "manli111111111111111111111111111";
    @Value("${wechatpay.notifyUrl}")
    String notify_url ;
    @Value("${wechatpay.refuseNotifyUrl}")
    String refuse_notify_url ;
    //漫狸科技工作室商户号
    String sub_mch_id = "1601704787";
    SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
    /**
     * 多商户多笔支付
     * 统一商户orderNoMain相同orderNoSub不同
     * 不同商户orderNoMain不同
     * @param queryParamsPayInfos
     * @param request
     * @return
     * @throws Exception
     */
    public Result payForMutiProductAndBuyCar(List<QueryParamsPayInfo> queryParamsPayInfos, HttpServletRequest request) throws Exception {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        List<OrderInfo> listOrderInfo = new ArrayList();
        List<Map> prepayList = new ArrayList<>();
        for (QueryParamsPayInfo paramsPayInfo : queryParamsPayInfos) {
            //redis加锁,抢锁等待时间比较重要，过期时间不重要
            String redisKey = "payForMutiProductAndBuyCar_"+paramsPayInfo.getGoodsDefId()+"_"+paramsPayInfo.getGoodsModelId();
            String identifier =  redisUtil.lockWithTimeout(redisKey,2000,3000);
            if(identifier == null){
                return ResultUtil.success(ResultEnums.REDIS_LOCK_TIME_OUT);
            }
            //查询产品状态和库存
            StockInfo stockInfo = checkStock(paramsPayInfo,sessionInfo);
            if(stockInfo.getNoPayOrderNoMain() != null){
                Map map = new HashMap();
                map.put("mainOrderNo" , stockInfo.getNoPayOrderNoMain());
                prepayList.add(map);
            }
            //设置分订单号
            long subOrderNo = idWorker.nextId();
            paramsPayInfo.setSubOrderId(String.valueOf(subOrderNo));
            //组装orderInfoList
            OrderInfo orderInfo = convertToOrderInfo(sessionInfo , paramsPayInfo , stockInfo);
            listOrderInfo.add(orderInfo);
            //redis解锁
            redisUtil.lockDel(redisKey,identifier);
        }

        //判断是否已经有待支付订单了
        //已经有了则直接返回
        if(prepayList.size() > 0){
            return ResultUtil.success(prepayList);
        }

        //按店铺归类
        Map<String, List<OrderInfo>> map = listOrderInfo.stream().collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
        for(Map.Entry<String, List<OrderInfo>> entry : map.entrySet()){
            //预下单
            long mainOrderNo = idWorker.nextId();
            Map<String,String> prepayMap = convertToWxPayPojoV2(entry.getValue(),String.valueOf(mainOrderNo),request);
            //增加主订单号
            prepayMap.put("mainOrderNo",String.valueOf(mainOrderNo));
            prepayList.add(prepayMap);
        }
        return ResultUtil.success(prepayList);
    }

    public Result payForPreParOrder(List<QueryParamsPayInfo> queryParamsPayInfos, HttpServletRequest request) throws Exception {
        List<OrderInfo> listOrderInfo = new ArrayList<>();
        //通过subOrderId获取到订单信息
        for (QueryParamsPayInfo paramPayInfo:  queryParamsPayInfos ) {
            List<OrderInfo> orderInfos = orderInfoDao.createLambdaQuery().andEq("order_no_main",paramPayInfo.getMainOrderId())
                    .andEq("status",0).select();
            if(orderInfos!=null){
                for (OrderInfo orderInfo: orderInfos) {
                    listOrderInfo.add(orderInfo);
                }
            }
        }
        if(listOrderInfo.size() == 0){
            throw new MyException(ResultEnums.UNKONW_ORDER_INFO);
        }
        //按店铺归类
        List<Map> prepayList = new ArrayList<>();
        Map<String, List<OrderInfo>> map = listOrderInfo.stream().collect(Collectors.groupingBy(e -> fetchGroupKey(e)));
        for(Map.Entry<String, List<OrderInfo>> entry : map.entrySet()){
            Map<String,String> prepayMap = convertToWxPayPojoV2(entry.getValue(), null ,request);
            prepayList.add(prepayMap);
        }
        return ResultUtil.success(prepayList);
    }

    /**
     * stream分组排序多字段
     * @param orderInfo
     * @return
     */
    private static String fetchGroupKey(OrderInfo orderInfo){
        return orderInfo.getBranchId() +"#"+ orderInfo.getPartnerId();
    }

    /**
     * orderInfos装换为微信支付
     * orderNoMain在新订单的时候需要传入在待支付订单中不需要传入
     * @param orderInfos
     * @return
     */
    private Map convertToWxPayPojoV2(List<OrderInfo> orderInfos,String orderNoMain,HttpServletRequest request) throws Exception {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        //写入数据库
        if(orderNoMain != null){
            for (OrderInfo orderInfo:orderInfos) {
                orderInfo.setOrderNoMain(orderNoMain);
                orderInfoDao.insertReturnKey(orderInfo);
                //加入延迟取消
                delayCancelOrder(orderInfo);
                //将购物车的商品移除
                removeGoodsFromBuyCar(orderInfo);
                //将他从店铺记录移除
                removeGoodsFromStore(orderInfo);
            }
        }
        MyWxPayConfig config = new MyWxPayConfig(certPath, appID, mchID, key);
        WxPayPojoV2 wxPayPojoV2 = new WxPayPojoV2();
        wxPayPojoV2.setAppid(appID);
        wxPayPojoV2.setMch_id(mchID);
        /**
         * 商户支付如果没有将支付给漫狸科技工作室
         */
        String sub_much_id = orderInfos.get(0).getPayMchId() == null ? sub_mch_id : orderInfos.get(0).getPayMchId();
        wxPayPojoV2.setSub_mch_id(sub_much_id);
        wxPayPojoV2.setBody("漫淘淘支付中心");
        // attach直接写入数据库则不需要发给微信支付
        // wxPayPojoV2.setAttach(orderInfos.get(0).getAttach());
        wxPayPojoV2.setOut_trade_no(orderNoMain!=null?orderNoMain:orderInfos.get(0).getOrderNoMain());
        double sum = orderInfos.stream().mapToDouble(t -> t.getShouldPayPrice()).sum();
        //单位分 * 100
        String totalFee = new BigDecimal(String.valueOf(sum)).multiply(new BigDecimal(100)).toBigInteger().toString();
        wxPayPojoV2.setTotal_fee(totalFee);
        wxPayPojoV2.setSpbill_create_ip(IPUtils.getRealIP(request));
        wxPayPojoV2.setNotify_url(notify_url);
        wxPayPojoV2.setTrade_type(orderInfos.get(0).getTradeType());
        //wxPayPojoV2.setOpenid(orderInfos.get(0).getBuyerOpenid());
        if(sessionInfo.getWeChatUserInfo().getSource() == 2){
            //小程序
            wxPayPojoV2.setSub_appid(appIdMiniprogram);
            wxPayPojoV2.setSub_openid(sessionInfo.getWeChatUserInfo().getOpenid());
            //小程序下面openid不用填写
            //wxPayPojoV2.setOpenid(null);
        }else{
            //公众号
            wxPayPojoV2.setSub_appid(appID);
            wxPayPojoV2.setSub_openid(sessionInfo.getWeChatUserInfo().getOpenid());
        }
        if(wxPayPojoV2.getTrade_type().equals("JSAPI")){

        }

        wxPayPojoV2.setProduct_id(String.valueOf(orderInfos.get(0).getGoodsModelId()));
        //设置优惠信息
        wxPayPojoV2.setGoods_tag(getGoodsTag(orderInfos));
        Map map = JSON.parseObject(JSON.toJSONString(wxPayPojoV2), Map.class);
        logger.info("payInfoParamToWxpay:{}",map);
        WXPay wxpay = new WXPay(config);
        Map<String, String> resp = wxpay.unifiedOrder(map);
        if(resp.get("return_code").equals("SUCCESS") && resp.get("result_code").equals("SUCCESS")){
            String noncestr = RandomUtils.getRandNumByLength(5);
            String timestamp = System.currentTimeMillis()/1000+"";
            String packageStr = "prepay_id="+resp.get("prepay_id");
            String signType = "MD5";
            String sign = WeChatSignUtils.getsigForWxPayMD5(wxPayPojoV2.getSub_appid(), timestamp, noncestr, packageStr, signType ,key);

            Map<String, String> retMap = new HashMap<>();
            retMap.put("noncestr", noncestr);
            retMap.put("timestamp", timestamp);
            retMap.put("sign", sign);
            retMap.put("appid", wxPayPojoV2.getSub_appid());
            retMap.put("signType", signType);
            retMap.put("packageStr", packageStr);
            return retMap;
        }else{
            throw new MyException(-1,resp.get("return_msg")+resp.get("err_code_des"));
        }
        //return null;
    }

    /**
     * 将从店铺记录移除
     * @param orderInfo
     */
    private void removeGoodsFromStore(OrderInfo orderInfo) {
        if(SourceSubEnums.DPXQ.getContent().equals(orderInfo.getSourceSub())){
            visitWantToBuyLogDao.executeUpdate(
                    "update visit_want_to_buy_log " +
                        "set " +
                        "goods_def_id = ? ," +
                        "goods_model_id = ? ," +
                        "status = 0 " +
                        "where unionid = ? ",
                    orderInfo.getGoodsDefId(),
                    orderInfo.getGoodsModelId(),
                    orderInfo.getBuyerUnionid());
        }
    }

    /**
     * 将购物车的商品移除
     * @param orderInfo
     */
    private void removeGoodsFromBuyCar(OrderInfo orderInfo) {
        if(SourceSubEnums.GWC.getContent().equals(orderInfo.getSourceSub())){
            buyCarLogDao.executeUpdate("" +
                    "update buy_car_log " +
                    "set status = 0 " +
                    "where goods_def_id = ? " +
                    "and   goods_model_id = ? " +
                    "and unionid = ? " , orderInfo.getGoodsDefId() , orderInfo.getGoodsModelId() , orderInfo.getBuyerUnionid());
        }
    }

    /**
     * 订单30分钟没有支付则关闭订单
     */
    public void delayCancelOrder(OrderInfo orderInfo){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderNoMain",orderInfo.getOrderNoMain());
        jsonObject.put("orderNoSub",orderInfo.getOrderNoSub());
        Message message = new Message(jsonObject.toJSONString(), 1000 * 60*60L);
        String queueName = QueueNameEnums.Delay_PREPAY.getContent();
        BlockingQueue<Message> delayedQueue = new DelayQueue<>();

        RedisZSetDelayedQueue redisZSetDelayedQueue = new RedisZSetDelayedQueue(redisTemplate, queueName, delayedQueue);

        redisZSetDelayedQueue.offerMessage(message);
        redisTaskUtil.asyncZSetTask(queueName);
    }

    /**
     * 装换成orderInfo
     * @param sessionInfo
     * @param paramsPayInfo
     * @param stockInfo
     * @return
     */
    private OrderInfo convertToOrderInfo(SessionInfo sessionInfo, QueryParamsPayInfo paramsPayInfo, StockInfo stockInfo) {
        OrderInfo orderInfo = new OrderInfo();

        orderInfo.setAttach(paramsPayInfo.getAttach());
        orderInfo.setBranchId(stockInfo.getBranchId());
        orderInfo.setPartnerId(stockInfo.getPartnerId());
        orderInfo.setBuyerOpenid(sessionInfo.getWeChatUserInfo().getOpenid());
        orderInfo.setBuyerUnionid(sessionInfo.getWeChatUserInfo().getUnionid());
        orderInfo.setShareOpenid(paramsPayInfo.getShareOpenid());
        orderInfo.setShareUnionid(paramsPayInfo.getShareUnionid());

        //获取默认地址
        /*List<WeChatUserInfoAddress> addresses = weChatUserInfoAddressDao.createLambdaQuery()
                .andEq("unionid",sessionInfo.getWeChatUserInfo().getUnionid())
                .andEq("status",1)
                .appendSql(" order by default_address desc ")
                .select();

        if(addresses.size()>0){
            WeChatUserInfoAddress firstAddress = addresses.get(0);
            String firstAddressStr = firstAddress.getProvinceName()+firstAddress.getCityName()+firstAddress.getAreaName()+firstAddress.getStreetName();
            orderInfo.setBuyerAddress(firstAddressStr);
            orderInfo.setBuyerPhone(firstAddress.getBuyerPhone());
            orderInfo.setBuyerName(firstAddress.getBuyerName());
        }*/


        orderInfo.setBuyerLatitude(paramsPayInfo.getLatitude());
        orderInfo.setBuyerLongitude(paramsPayInfo.getLongitude());
        LocationPoint locationPointWgs = LocationUtils.gcj02_To_Wgs84(new LocationPoint(Double.valueOf(paramsPayInfo.getLongitude()),Double.valueOf(paramsPayInfo.getLatitude())));
        orderInfo.setBuyerLatitudeWgs(String.valueOf(locationPointWgs.getLatitude()));
        orderInfo.setBuyerLongitudeWgs(String.valueOf(locationPointWgs.getLongitude()));
        orderInfo.setTradeType(paramsPayInfo.getTradeType());
        orderInfo.setSource(paramsPayInfo.getSource());
        orderInfo.setSourceSub(paramsPayInfo.getSourceSub());
        //orderInfo.setOrderNoMain(paramsPayInfo.getMainOrderId()); 暂时不需要设置总订单id
        orderInfo.setOrderNoSub(paramsPayInfo.getSubOrderId());
        orderInfo.setGoodsDefId(paramsPayInfo.getGoodsDefId());
        orderInfo.setGoodsModelId(paramsPayInfo.getGoodsModelId());
        orderInfo.setCommissionPrice(getCommissionPrice(stockInfo));
        orderInfo.setGoodsModelCost(stockInfo.getGoodsModelCost());
        orderInfo.setGoodsModelSalePrice(stockInfo.getGoodsModelSalePrice());
        orderInfo.setGoodsModelChannelPrice(stockInfo.getGoodsModelChannelPrice());
        orderInfo.setActivityTypeId(paramsPayInfo.getActivityTypeId());
        orderInfo.setCreateTime(new Date());
        orderInfo.setBuyCount(paramsPayInfo.getBuyCount());
        //orderInfo.setPayPrice(new BigDecimal(String.valueOf(stockInfo.getPayUnitPrice())).multiply(new BigDecimal(String.valueOf(paramsPayInfo.getBuyCount()))).doubleValue());
        if(stockInfo.getWechatMchId() == null || "".equals(stockInfo.getWechatMchId().trim())){
            orderInfo.setPayMchId(sub_mch_id);
        }else{
            orderInfo.setPayMchId(stockInfo.getWechatMchId());
        }

        orderInfo.setShouldPayPrice(new BigDecimal(String.valueOf(stockInfo.getPayUnitPrice())).multiply(new BigDecimal(String.valueOf(paramsPayInfo.getBuyCount()))).doubleValue());
        //待支付
        orderInfo.setStatus(0);
        //配送模式
        orderInfo.setBuyMethod(stockInfo.getBuyMethod());
        return orderInfo;
    }

    /**
     * 检查库存及商品是否有效总控制
     * @param paramsPayInfo
     * @return
     */

    public StockInfo checkStock(QueryParamsPayInfo paramsPayInfo , SessionInfo sessionInfo){
        //redis加锁,抢锁等待时间比较重要，过期时间不重要
        //String redisKey = "checkStock_"+paramsPayInfo.getGoodsDefId()+"_"+paramsPayInfo.getGoodsModelId();

        StockInfo stockInfo;
        //String identifier =  redisUtil.lockWithTimeout(redisKey,2000,3000);
        if(paramsPayInfo.getActivityTypeId() == null){
            stockInfo = checkStockNoActivity(paramsPayInfo,sessionInfo);
        }else{
            stockInfo =  checkStockIsActivity(paramsPayInfo,sessionInfo);
        }

        //redis解锁
        //redisUtil.lockDel(redisKey,identifier);
        return  stockInfo;
    }

    /**
     * 获取微信优惠标记
     * @param orderInfoList
     * @return
     */
    private String getGoodsTag(List<OrderInfo> orderInfoList) {
        //TODO 获取微信优惠标记
        String goodsTag = "";
        for(OrderInfo orderInfo : orderInfoList){
            Integer branchId = orderInfo.getBranchId();
            Integer partnerId = orderInfo.getPartnerId();
            if(partnerId == null){
                partnerId = 0 ;
            }
            goodsTag = branchId+"|"+partnerId+"|wechatgoodstag";
            break;
        }
        return goodsTag;
    }

    /**
     * 获取微信优惠标记
     * @param stockInfo
     * @return
     */
    private Double getCommissionPrice(StockInfo stockInfo) {
        //TODO 获取佣金标记
        return null;
    }

    /**
     * 非活动产品
     * 检查库存及商品是否有效
     * @param paramsPayInfo
     * @return
     */
    public StockInfo checkStockNoActivity(QueryParamsPayInfo paramsPayInfo , SessionInfo sessionInfo){
        String sql =
                "select * from view_stock_info vsi " +
                        "where vsi.goods_def_id = ? " +
                        "and vsi.goods_model_id = ? " ;
        SQLReady sqlReady = new SQLReady(sql,paramsPayInfo.getGoodsDefId(),paramsPayInfo.getGoodsModelId());
        List<StockInfo> stockInfos = sqlManager.execute(sqlReady,StockInfo.class);
        StockInfo stockInfo ;
        if(stockInfos.size() == 1){
            stockInfo = stockInfos.get(0);
        }else{
            throw new MyException(ResultEnums.MORE_THAN_ONE_OR_NO_GOODS_FIND);
        }
        if(stockInfo.getGoodsDefStatus()!= 1 || stockInfo.getGoodsModelStatus() != 1){
            throw new MyException(ResultEnums.GOODS_INFO_NOT_USEFUL);
        }
        if(stockInfo.getStockCount().intValue() < paramsPayInfo.getBuyCount().intValue() ){
            throw new MyException(ResultEnums.STOCK_COUNT_LESS_THAN_BUY_COUNT);
        }
        //查询支付单价
        if(sessionInfo.getWeChatUserInfo() != null){
            //用户端
            stockInfo.setPayUnitPrice(stockInfo.getGoodsModelSalePrice());
        }
        if(sessionInfo.getWeChatUserInfo() == null){
            //商户端
            stockInfo.setPayUnitPrice(stockInfo.getGoodsModelChannelPrice());
        }
        if(stockInfo.getPayUnitPrice() == null){
            throw new MyException(ResultEnums.UNKONW_PAY_SOURCE);
        }

        return stockInfo;
    }

    public StockInfo checkStockIsActivity(QueryParamsPayInfo paramsPayInfo , SessionInfo sessionInfo){
        Double payUnitPrice = null;
        String sql =
                "select * from view_stock_info vsi " +
                        "where vsi.goods_def_id = ? " +
                        "and vsi.goods_model_id = ? " +
                        "and vsi.status not in (-1,3) " +
                        "group by vsi.goods_def_id,vsi.goods_model_id ";
        SQLReady sqlReady = new SQLReady(sql,paramsPayInfo.getGoodsDefId(),paramsPayInfo.getGoodsModelId());
        List<StockInfo> stockInfos = sqlManager.execute(sqlReady,StockInfo.class);
        StockInfo stockInfo ;
        if(stockInfos.size() == 1){
            stockInfo = stockInfos.get(0);
        }else{
            throw new MyException(ResultEnums.MORE_THAN_ONE_OR_NO_GOODS_FIND);
        }
        if(stockInfo.getGoodsDefStatus()!= 1 || stockInfo.getGoodsModelStatus() != 1){
            throw new MyException(ResultEnums.GOODS_INFO_NOT_USEFUL);
        }
        if(stockInfo.getStockCount().intValue() < paramsPayInfo.getBuyCount().intValue() ){
            throw new MyException(ResultEnums.STOCK_COUNT_LESS_THAN_BUY_COUNT);
        }
        QueryParamsCheckPayPrice queryParamsCheckPayPrice = new QueryParamsCheckPayPrice();
        queryParamsCheckPayPrice.setGoodsDefId(paramsPayInfo.getGoodsDefId());
        queryParamsCheckPayPrice.setGoodsModelId(paramsPayInfo.getGoodsModelId());
        queryParamsCheckPayPrice.setUnionid(sessionInfo.getWeChatUserInfo().getUnionid());

        //判断是否已经有待付款订单
        ViewOrderGoods viewOrderGoods = viewOrderGoodsDao.createLambdaQuery().andEq("status", 0)
                .andEq("buyer_unionid",sessionInfo.getWeChatUserInfo().getUnionid())
                .andEq("goods_def_id",paramsPayInfo.getGoodsDefId())
                .andEq("goods_model_id",paramsPayInfo.getGoodsModelId())
                .andEq("activity_type_id",paramsPayInfo.getActivityTypeId())
                .andEq("buy_count",paramsPayInfo.getBuyCount()).single();
        if(viewOrderGoods != null){
            stockInfo.setNoPayOrderNoMain(viewOrderGoods.getOrderNoMain());
        }

        //砍价金额
        if(paramsPayInfo.getActivityTypeId().equals(1)){
            queryParamsCheckPayPrice.setActivityType(1);
            payUnitPrice = wechatShopService.checkActivityPayPrice(queryParamsCheckPayPrice);
            stockInfo.setGoodsModelSalePrice(payUnitPrice);
        }
        //拼团金额 = 销售价
        if(paramsPayInfo.getActivityTypeId().equals(2)){
            queryParamsCheckPayPrice.setActivityType(2);
            payUnitPrice = wechatShopService.checkActivityPayPrice(queryParamsCheckPayPrice);
        }
        //一元拍卖金额 取活动最高价
        if(paramsPayInfo.getActivityTypeId().equals(3)){
            queryParamsCheckPayPrice.setActivityType(3);
            payUnitPrice = wechatShopService.checkActivityPayPrice(queryParamsCheckPayPrice);
            //已支付一元参与
            payUnitPrice = payUnitPrice - 1 ;
            stockInfo.setGoodsModelSalePrice(payUnitPrice);
        }
        if(payUnitPrice == null){
            throw new MyException(ResultEnums.ACTIVITY_CANT_FOR_PAY_OPTION);
        }
        //计算支付单价
        stockInfo.setPayUnitPrice(payUnitPrice);
        //查询活动是否在结束前三天
        if(checkActivityCanPay(paramsPayInfo)){
            throw new MyException(ResultEnums.ACTIVITY_CANT_FOR_PAY_TIME_OUT);
        }
        return stockInfo;
    }

    public boolean checkActivityCanPay(QueryParamsPayInfo paramsPayInfo ){
        ActivityGoods activityGoods = activityGoodsDao.createLambdaQuery().andEq("activity_type_id",paramsPayInfo.getActivityTypeId())
                .andEq("goods_def_id",paramsPayInfo.getGoodsDefId()).single();
        if(!activityGoods.getStatus().equals("1")){
            throw new MyException(ResultEnums.ACTIVITY_NOT_OPEN);
        }
        //计算结束时间是否超过三天
        DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateTime endDateTime = DateTime.parse(simp.format(activityGoods.getActivityEndTime()) , fmt);
        DateTime nowDate = new DateTime();
        int days= Days.daysBetween(endDateTime, nowDate).getDays();
        if(days > 3){
            return true;
        }
        return false;
    }


    /**
     * 支付成功通知
     * @param notifyData
     * @return
     */
    public String orderPayNotify(String notifyData) throws Exception{
        MyWxPayConfig config = new MyWxPayConfig(certPath, appID, mchID, key);
        WXPay wxpay = new WXPay(config);
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        logger.info(notifyMap.toString());
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            String return_code =  (String) notifyMap.get("return_code");
            if(WXPayConstants.SUCCESS.equalsIgnoreCase(return_code)){
                // 签名正确
                // 进行处理。 获取总的订单号更新状态从 0 待支付变成 1 支付
                String out_trade_no = notifyMap.get("out_trade_no");
                //String attach = notifyMap.get("attach");
                String time_end = notifyMap.get("time_end");
                String transaction_id = notifyMap.get("transaction_id");
                //现金支付金额
                float pay_price = new BigDecimal(notifyMap.get("cash_fee")).divide(new BigDecimal("100")).floatValue();
                //订单金额减去现金支付金额等于订单总优惠金额
                float preferential_price = (Integer.valueOf(notifyMap.get("total_fee")) - Integer.valueOf(notifyMap.get("cash_fee")))/100;
                // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
                String sql =
                        "update order_info " +
                        "set " +
                        "pay_time = ? ," +
                        "pay_price = ? ," +
                        "transaction_id = ? ," +
                        "preferential_price = ? ," +
                        "status = 1 " +
                        "where " +
                        "order_no_main= ? and status = 0 " ;
                orderInfoDao.executeUpdate(sql,time_end,pay_price,transaction_id,preferential_price,out_trade_no);
                orderPaySuccess(out_trade_no);
            }else{
                logger.error(notifyMap.get("return_msg"));
            }
            return "<xml>" +
                    "  <return_code><![CDATA[SUCCESS]]></return_code>" +
                    "  <return_msg><![CDATA[OK]]></return_msg>" +
                    "</xml>";

        }else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误
        }
        return null;
    }

    //支付成功回调
    private void orderPaySuccess(String out_trade_no) {
        try{
            //获取订单信息
            OrderInfo orderInfo = orderInfoDao.createLambdaQuery().andEq("order_no_main",out_trade_no).single();
            //判断是否是拼团活动
            if(orderInfo.getActivityTypeId() != null && orderInfo.getActivityTypeId().intValue() == 2 && orderInfo.getStatus() == 1){
                orderPaySuccessForPingTuan(orderInfo);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *
     * @param orderInfo
     */
    private void orderPaySuccessForPingTuan(OrderInfo orderInfo) {
        QueryParamsBargainAdd queryParamsBargainAdd = new QueryParamsBargainAdd();
        queryParamsBargainAdd.setGoodsDefId(orderInfo.getGoodsDefId());
        queryParamsBargainAdd.setGoodsModelId(orderInfo.getGoodsModelId());
        queryParamsBargainAdd.setSponsorUnionid(orderInfo.getAttach());
        wechatShopService.groupAddForPaySuccess(queryParamsBargainAdd , orderInfo);
    }

    /**
     * 退款成功通知
     * @param notifyData
     * @return
     */
    public String orderRefuseNotify(String notifyData) throws Exception {
        String resXml = "";
        String resSuccessXml = "<xml> " +
                "  <return_code><![CDATA[SUCCESS]]></return_code> " +
                "  <return_msg><![CDATA[OK]]></return_msg> " +
                "</xml>";
        String resFailXml = "<xml> " +
                "  <return_code><![CDATA[FAIL]]></return_code> " +
                "  <return_msg><![CDATA[FAIL]]></return_msg> " +
                "</xml>";
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        String return_code =  (String) notifyMap.get("return_code");
        String return_msg =  (String) notifyMap.get("return_msg");
        String req_info = (String) notifyMap.get("req_info");//返回的加密信息，需要解密
        //对加密串req_info做base64解码，得到加密串B
        if (WXPayConstants.SUCCESS.equalsIgnoreCase(return_code)) {

            logger.info("refund:微信退款----返回成功");

            /**
             * 解密方式
             * 解密步骤如下：
             * （1）对加密串A做base64解码，得到加密串B
             * （2）对商户key做md5，得到32位小写key* ( key设置路径：微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )
             * （3）用key*对加密串B做AES-256-ECB解密（PKCS7Padding）
             */
            String resultStr = AESUtil.decryptData(req_info, AESUtil.MD5(key).toLowerCase());;

            // WXPayUtil.getLogger().info("refund:解密后的字符串:" + resultStr);
            Map<String, String> aesMap = WXPayUtil.xmlToMap(resultStr);


            /** 以下为返回的加密字段： **/
            //	商户退款单号	是	String(64)	1.21775E+27	商户退款单号
            String out_refund_no = aesMap.get("out_refund_no");
            //	退款状态	是	String(16)	SUCCESS	SUCCESS-退款成功、CHANGE-退款异常、REFUNDCLOSE—退款关闭
            String refund_status = aesMap.get("refund_status");
            //	商户订单号	是	String(32)	1.21775E+27	商户系统内部的订单号
            String out_trade_no = aesMap.get("out_trade_no");
            //	微信订单号	是	String(32)	1.21775E+27	微信订单号
            /*String transaction_id = null;
            //	微信退款单号	是	String(32)	1.21775E+27	微信退款单号
            String refund_id = null;
            //	订单金额	是	Int	100	订单总金额，单位为分，只能为整数，详见支付金额
            String total_fee = null;
            //	应结订单金额	否	Int	100	当该订单有使用非充值券时，返回此字段。应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
            String settlement_total_fee = null;
            //	申请退款金额	是	Int	100	退款总金额,单位为分
            String refund_fee = null;
            //	退款金额	是	Int	100	退款金额=申请退款金额-非充值代金券退款金额，退款金额<=申请退款金额
            String settlement_refund_fee = null;*/

            // 退款是否成功
            if (!WXPayConstants.SUCCESS.equals(refund_status)) {
                resXml = resFailXml;
            } else {

                String success_time = aesMap.get("success_time");
                String transaction_id = aesMap.get("transaction_id");
                String settlement_refund_fee = aesMap.get("settlement_refund_fee");
                // 将订单状态从已支付改为退款
                String sql =
                        "update order_info " +
                                "set " +
                                "status = 3 ," +
                                "transaction_id = ? ," +
                                "refuse_time = ?," +
                                "refuse_price = ? " +
                                "where " +
                                "order_no_sub = ? " ;
                orderInfoDao.executeUpdate(sql,transaction_id,success_time,settlement_refund_fee,out_refund_no);
                // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = resSuccessXml;
            }
            // 根据付款单号查询付款记录 out_refund_no

            // 付款记录修改 & 记录付款日志
            /*if (payment != null) {
                WXPayUtil.getLogger().error("refund:微信支付回调：修改支付单");
            } else {
                WXPayUtil.getLogger().error("refund:微信支付回调：找不到对应的支付单");
            }*/


        } else {
            WXPayUtil.getLogger().error("refund:支付失败,错误信息：" + return_msg);
            resXml = resFailXml;
        }
        return resXml;
    }
    public Result orderRefuseApply(OrderRefuseApply refuseApply , HttpServletRequest request) {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        //查询是否已经申请了
        OrderRefuseApply orderRefuseApply = orderRefuseApplyDao.createLambdaQuery()
                .appendSql(" where status= -1 " +
                        " and order_no_main =  " + refuseApply.getOrderNoMain() +
                        " and order_no_sub =  " + refuseApply.getOrderNoSub()).single();
        //写入order_refuse_apply
        if(orderRefuseApply!=null){
            throw new MyException(ResultEnums.ORDER_APPLY_EXITS);
        }else{
            OrderRefuseApply apply = new OrderRefuseApply();
            apply.setApplyOpenid(sessionInfo.getWeChatUserInfo().getOpenid());
            apply.setApplyUnionid(sessionInfo.getWeChatUserInfo().getUnionid());
            apply.setApplyTime(new Date());
            apply.setBranchId(refuseApply.getBranchId());
            apply.setPartnerId(refuseApply.getPartnerId());
            apply.setGoodsDefId(refuseApply.getGoodsDefId());
            apply.setGoodsModelId(refuseApply.getGoodsModelId());
            apply.setOrderNoMain(refuseApply.getOrderNoMain());
            apply.setOrderNoSub(refuseApply.getOrderNoSub());
            apply.setApplyRemark(refuseApply.getApplyRemark());
            apply.setStatus(-1);
            orderRefuseApplyDao.insert(apply);
            sendTemplateForApply(apply);
        }
        return ResultUtil.success("退款申请成功,请耐心等待");
    }

    //TODO 退款申请模板通知
    private void sendTemplateForApply(OrderRefuseApply apply) {
        try {
            //查询产品上架人员
            //sqlManager.execute(new SQLReady("",))
            //发送模板消息给上架人员
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public Result orderRefuseAudit(OrderRefuseApply refuseApply,HttpServletRequest request) throws Exception {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        OrderRefuseApply apply = orderRefuseApplyDao.createLambdaQuery()
                .andEq("order_refuse_apply_id",refuseApply.getOrderRefuseApplyId()).single();
        if(apply==null){
            return ResultUtil.error(ResultEnums.ORDER_APPLY_BEEN_AUDIT.getCode(),ResultEnums.ORDER_APPLY_BEEN_AUDIT.getMsg());
        }
        if(sessionInfo.getWeChatUserInfo() != null){
            //手机端审核
            if(apply.getPartnerId() == null){
                if(apply.getBranchId().intValue() != sessionInfo.getWeChatUserInfo().getStoreClerkBranchId().intValue()){
                    throw new MyException(ResultEnums.NO_PERMISSIONS_AUDIT_REFUSE);
                }
            }else{
                if(apply.getPartnerId().intValue() != sessionInfo.getWeChatUserInfo().getStoreClerkPartnerId().intValue()){
                    throw new MyException(ResultEnums.NO_PERMISSIONS_AUDIT_REFUSE);
                }
            }
        }else{
            //电脑端审核
            if(apply.getPartnerId() == null){
                if(apply.getBranchId().intValue() != sessionInfo.getBranchId().intValue()){
                    throw new MyException(ResultEnums.NO_PERMISSIONS_AUDIT_REFUSE);
                }
            }else{
                if(apply.getPartnerId().intValue() != sessionInfo.getPartnerId().intValue()){
                    throw new MyException(ResultEnums.NO_PERMISSIONS_AUDIT_REFUSE);
                }
            }
        }
        //更新order_refuse_apply
        apply.setAuditTime(new Date());
        apply.setStatus(refuseApply.getStatus());
        apply.setAuditRemark(refuseApply.getAuditRemark());
        if(sessionInfo.getWeChatUserInfo()!=null){
            apply.setAuditOpenid(sessionInfo.getWeChatUserInfo().getOpenid());
            apply.setAuditUnionid(sessionInfo.getWeChatUserInfo().getUnionid());
            apply.setAuditUserId(sessionInfo.getWeChatUserInfo().getStoreClerkUserId());
        }else{
            apply.setAuditUserId(sessionInfo.getUserId());
        }
        //更新
        orderRefuseApplyDao.updateById(apply);

        if(refuseApply.getStatus().intValue() == 1 ){
            //申请审核通过
            //发起退款等待通知
            OrderInfo orderInfo = orderInfoDao.createLambdaQuery().
                    andEq("order_no_main",apply.getOrderNoMain()).
                    andEq("order_no_sub",apply.getOrderNoSub()).single();
            refuseOrderInfoSendToWechat(orderInfo);
        }
        return ResultUtil.success("退款申请已审核");
    }

    public void refuseOrderInfoSendToWechat(OrderInfo orderInfo) throws Exception {
        MyWxPayConfig config = new MyWxPayConfig(certPath, appID, mchID, key);
        WXPay wxpay = new WXPay(config);
        WxPayPojoV2 wxPayPojoV2 = new WxPayPojoV2();
        wxPayPojoV2.setAppid(appID);
        wxPayPojoV2.setMch_id(mchID);
        wxPayPojoV2.setSub_mch_id(orderInfo.getPayMchId());
        wxPayPojoV2.setOut_trade_no(orderInfo.getOrderNoMain());
        //计算订单总金额
        String total_fee = new BigDecimal(String.valueOf(orderInfo.getPayPrice()))
                .add(new BigDecimal(String.valueOf(orderInfo.getPreferentialPrice())))
                .multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        wxPayPojoV2.setTotal_fee(total_fee);
        wxPayPojoV2.setOut_refund_no(orderInfo.getOrderNoSub());
        String refund_fee = null ;
        if(orderInfo.getSource().indexOf("phone")>-1){
            refund_fee = new BigDecimal(String.valueOf(orderInfo.getGoodsModelSalePrice()))
                    .multiply(new BigDecimal(String.valueOf(orderInfo.getBuyCount())))
                    .multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        }else{
            refund_fee = new BigDecimal(String.valueOf(orderInfo.getGoodsModelChannelPrice()))
                    .multiply(new BigDecimal(String.valueOf(orderInfo.getBuyCount())))
                    .multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString();
        }

        wxPayPojoV2.setRefund_fee(refund_fee);
        //wxPayPojoV2.setRefund_desc("售完");
        wxPayPojoV2.setNotify_url(refuse_notify_url);

        Map map = JSON.parseObject(JSON.toJSONString(wxPayPojoV2), Map.class);
        Map<String, String> resp = wxpay.refund(map);
        logger.info(resp.toString());
        if(resp.get("return_code").equals("SUCCESS")){
            if(!resp.get("result_code").equals("SUCCESS")){
                logger.error(resp.get("err_code_des").toString());
                throw new MyException(-1,resp.get("err_code_des").toString());
            }
        }else{
            logger.error(resp.get("return_msg").toString());
            throw new MyException(-1,resp.get("return_msg").toString());
        }
    }

    //TODO 活动结束发起退款问题


    public int orderStatusSearch(QueryParamsPayInfo payInfo) throws Exception {
        MyWxPayConfig config = new MyWxPayConfig(certPath, appID, mchID, key);
        WXPay wxpay = new WXPay(config);

        //获取订单信息
        OrderInfo orderInfo = orderInfoDao.createLambdaQuery().andEq("order_no_main",payInfo.getMainOrderId())
                .andEq("order_no_sub",payInfo.getSubOrderId()).single();
        if(orderInfo == null){
            throw new MyException(ResultEnums.UNKONW_ORDER_INFO);
        }

        //查询订单状态
        Map<String, String> data = new HashMap<String, String>();
        data.put("out_trade_no", orderInfo.getOrderNoMain());
        data.put("sub_mch_id", orderInfo.getPayMchId());

        // -1取消订单 0 待支付 1支付成功  2 退款中  3已退款  4 已使用（已核销）
        Integer orderInfoStatus = 0;
        try {
            Map<String, String> resp = wxpay.orderQuery(data);
            logger.info(resp.toString());
            if (!WXPayConstants.SUCCESS.equals(resp.get("return_code"))) {
                throw new MyException(ResultEnums.UNKONW_ORDER_INFO);
            }
            String search_trade_state = (String)resp.get("trade_state");

            if(search_trade_state.equals("SUCCESS")){
                orderInfoStatus = 0 ;
            }else if(search_trade_state.equals("NOTPAY")){
                orderInfoStatus = 0 ;
            }else if(search_trade_state.equals("CLOSED")){
                orderInfoStatus = -1 ;
            }else if(search_trade_state.equals("USERPAYING")){
                orderInfoStatus = 0 ;
            }else if(search_trade_state.equals("PAYERROR")){
                orderInfoStatus = 0 ;
            }else if(search_trade_state.equals("REFUND")) {

            }else{

            }
            //查询退款
            data.put("refund_id", orderInfo.getOrderNoSub());
            resp = wxpay.refundQuery(data);
            if (WXPayConstants.SUCCESS.equals(resp.get("return_code"))) {
                orderInfoStatus = 3;
            }
            //更新订单状态
            if(orderInfoStatus.intValue() != orderInfo.getStatus().intValue()){
                if(orderInfo.getStatus().intValue() != 3 || orderInfo.getStatus().intValue() != 4){
                    //退款和已使用不能发送状态改变
                    orderInfo.setStatus(orderInfoStatus);
                    orderInfoDao.updateTemplateById(orderInfo);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderInfoStatus;
    }

    public Result updateOrderInfoByMainOrderNo(QueryParamsPayInfo queryParamsPayInfo, HttpServletRequest request) {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        orderInfoDao.executeUpdate(
                "update order_info " +
                    "set " +
                    "buyer_address = ?," +
                    "buyer_phone = ?, " +
                    "buyer_name = ? " +
                    "where " +
                    "order_no_main = ? " +
                    "and buyer_unionid = ?  " ,
                queryParamsPayInfo.getBuyerAddress(),
                queryParamsPayInfo.getBuyerPhone(),
                queryParamsPayInfo.getBuyerName(),
                queryParamsPayInfo.getMainOrderId(),
                sessionInfo.getWeChatUserInfo().getUnionid());
        return ResultUtil.success("订单信息更新成功");
    }

    public Result getGoodsInfoByMainOrderNo(QueryParamsPayInfo queryParamsPayInfo, HttpServletRequest request) {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);

        List<ViewOrderGoods> viewOrderGoods = viewOrderGoodsDao.createLambdaQuery()
                .andEq("order_no_main",queryParamsPayInfo.getMainOrderId()).select();

        //获取默认地址
        WeChatUserInfoAddress address = weChatUserInfoAddressDao.createLambdaQuery()
                .andEq("unionid",sessionInfo.getWeChatUserInfo().getUnionid())
                .andEq("status",1)
                .appendSql(" order by default_address desc ")
                .single();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("viewOrderGoods",viewOrderGoods);
        jsonObject.put("address",address);
        return ResultUtil.success(jsonObject);
    }


    public Result payForNoGoodsOrder(QueryParamsPayInfo queryParamsPayInfo, HttpServletRequest request) throws Exception {
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        String orderNoMain = String.valueOf(idWorker.nextId());
        String orderNoSub = String.valueOf(idWorker.nextId());
        OrderInfo orderInfo = new OrderInfo();
        //订单号
        orderInfo.setOrderNoMain(orderNoMain);
        orderInfo.setOrderNoSub(orderNoSub);
        //支付商户信息
        orderInfo.setBranchId(queryParamsPayInfo.getBranchId());
        orderInfo.setPartnerId(queryParamsPayInfo.getPartnerId());
        //产品信息
        orderInfo.setGoodsDefId(queryParamsPayInfo.getGoodsDefId());
        orderInfo.setGoodsModelId(queryParamsPayInfo.getGoodsModelId());

        String payMchId = null ;
        if(queryParamsPayInfo.getPartnerId() == null){
            Branch branch = branchDao.createLambdaQuery().andEq("branch_id" , queryParamsPayInfo.getBranchId()).single();
            if(branch == null){
                throw new MyException(ResultEnums.UNKONW_BRANCH);
            }
            payMchId = branch.getBranchWechatMchId();
        }else{
            Partner partner = partnerDao.createLambdaQuery().andEq("partner_id" , queryParamsPayInfo.getPartnerId()).single();
            if(partner == null){
                throw new MyException(ResultEnums.UNKONW_PARTNER);
            }
            payMchId = partner.getPartnerWechatMchId();
        }
        if(payMchId == null || "".equals(payMchId)){
            payMchId = sub_mch_id ;
        }
        orderInfo.setPayMchId(payMchId);
        //输入金额支付 及销售价等价格设置
        if(orderInfo.getActivityTypeId() != null && orderInfo.getActivityTypeId() == 3){
            //如果是拍卖活动的预定金额为 1
            //校验拍卖活动
            checkYDDDOneYuan(queryParamsPayInfo , sessionInfo);
            queryParamsPayInfo.setShouldPayPrice(1d);
        }
        orderInfo.setShouldPayPrice(queryParamsPayInfo.getShouldPayPrice());
        orderInfo.setGoodsModelChannelPrice(queryParamsPayInfo.getShouldPayPrice());
        orderInfo.setGoodsModelSalePrice(queryParamsPayInfo.getShouldPayPrice());
        orderInfo.setGoodsModelCost(queryParamsPayInfo.getShouldPayPrice());
        orderInfo.setBuyCount(1);
        //支付人信息
        orderInfo.setBuyerUnionid(sessionInfo.getWeChatUserInfo().getUnionid());
        orderInfo.setBuyerOpenid(sessionInfo.getWeChatUserInfo().getOpenid());
        //支付状态待支付
        orderInfo.setCreateTime(new Date());
        orderInfo.setStatus(0);
        //其他信息
            //到店自取
        orderInfo.setBuyMethod("1");
            //经纬度
        orderInfo.setBuyerLatitude(queryParamsPayInfo.getLatitude());
        orderInfo.setBuyerLongitude(queryParamsPayInfo.getLongitude());
        LocationPoint locationPointWgs = LocationUtils.gcj02_To_Wgs84(new LocationPoint(Double.valueOf(queryParamsPayInfo.getLongitude()),Double.valueOf(queryParamsPayInfo.getLatitude())));
        orderInfo.setBuyerLatitudeWgs(String.valueOf(locationPointWgs.getLatitude()));
        orderInfo.setBuyerLongitudeWgs(String.valueOf(locationPointWgs.getLongitude()));
        //支付来源
        orderInfo.setTradeType(queryParamsPayInfo.getTradeType());
        orderInfo.setSource(queryParamsPayInfo.getSource());
        orderInfo.setSourceSub(queryParamsPayInfo.getSourceSub());
        //是否是活动
        orderInfo.setActivityTypeId(queryParamsPayInfo.getActivityTypeId());
        List<OrderInfo> orderInfos = new ArrayList<>();
        orderInfos.add(orderInfo);
        Map map = convertToWxPayPojoV2(orderInfos,orderNoMain,request);
        return ResultUtil.success(map);
    }
    //检验预定订单 一元拍卖
    private void checkYDDDOneYuan(QueryParamsPayInfo paramsPayInfo , SessionInfo sessionInfo) {
        ActivityGoods activityGoods = activityGoodsDao.createLambdaQuery().andEq("activity_type_id",paramsPayInfo.getActivityTypeId())
                .andEq("goods_def_id",paramsPayInfo.getGoodsDefId()).single();

        //计算结束时间是否超过三天
        DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        DateTime endDateTime = DateTime.parse(simp.format(activityGoods.getActivityEndTime()) , fmt);
        DateTime nowDate = new DateTime();

        // 判断时间是否没有结束
        if(endDateTime.getMillis() > nowDate.getMillis()){
            throw new MyException(ResultEnums.ACTIVITY_TIME_OUT);
        }

        //判断是否已经支付
        OrderInfo orderInfo = orderInfoDao.createLambdaQuery()
                .andEq("goods_model_id" , paramsPayInfo.getGoodsModelId())
                .andEq("buyer_unionid" , sessionInfo.getWeChatUserInfo().getUnionid())
                .andEq("status" , 1)
                .andEq("activity_type_id" , paramsPayInfo.getActivityTypeId())
                .andEq("source_sub" , "YDDD").single();
        if(orderInfo != null){
            throw new MyException(ResultEnums.HAS_PAY);
        }

    }


    public Result uploadLogoImg(MultipartFile file, HttpServletRequest request) throws Exception{
        File imgFile = FileUtil.multipartFileToFile(file);

        String result = WxpayV3Utils.imgUpload(imgFile,"");
        if(result != null){
            JSONObject json = JSONObject.parseObject(result);
            if(json.get("media_url") != null){
                return  ResultUtil.success(json.getString("media_url"));
            }
        }
        return ResultUtil.success();
    }

    @Transactional
    public Result branchCreateCoupons(CouponGrant couponGrant, HttpServletRequest request) throws Exception{
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        Integer branchId = sessionInfo.getBranchId();
        Integer partnerId = sessionInfo.getPartnerId();
        ObjectEmptyUtil.couponGrantIsEmpty(couponGrant);

//        Integer branchId = 1;
//        Integer partnerId = null;
        if(branchId != null && partnerId == null){
            if(branchId.intValue() == 1){
                //漫狸生成优惠券
                if(couponGrant.getPartnerIdList() != null && couponGrant.getPartnerIdList().size() > 0 ){
                    for(int i=0;i<couponGrant.getPartnerIdList().size();i++){
                        partnerCreateCouponBatch(couponGrant,couponGrant.getPartnerIdList().get(i));
                    }
                }
                if(couponGrant.getBranchIdList() != null && couponGrant.getPartnerIdList() == null && couponGrant.getBranchIdList().size() > 0 ){
                    for(int i=0;i<couponGrant.getBranchIdList().size();i++){
                        branchCreateCouponBatch(couponGrant,couponGrant.getBranchIdList().get(i));
                    }
                }
//                if(couponGrant.getBranchIdList() == null && couponGrant.getPartnerIdList() == null ){
//                    branchCreateCouponBatch(couponGrant,1);
//                }
            }else{
                //主商户自己生成优惠券
                branchCreateCouponBatch(couponGrant,branchId);
            }
        }
        if(partnerId != null){
            //子商户自己生成优惠券
            partnerCreateCouponBatch(couponGrant,partnerId);
        }

        return ResultUtil.success("代金券生成成功，5分钟内会自动激活");
    }

    public void branchCreateCouponBatch(CouponGrant couponGrant,Integer branchId)throws Exception{
        //商户自己生成优惠券批次

        //优惠券logo获取
        List<Branch> branches = branchDao.execute("select * from branch where branch_id = ?",branchId);
        if(branches.size() == 0){
            return;
        }
        if(branches.get(0).getBranchWechatMchId() == null){
            throw new MyException(-1,"商户未设置微信商户号");
        }
        if(couponGrant.getCombineUse() == null){
            throw new MyException(-1,"请选择是否可叠加使用");
        }
        String logoUrl = "";
        //使用漫狸的头像图片作为代金券logo
        Branch branch = branchDao.single(1);
        File file = HttpUtil.httpsGetImagAsFile(branch.getBranchHeadImg());
        String result = WxpayV3Utils.imgUpload(file,"1601420795");
        if(result != null){
            JSONObject json = JSONObject.parseObject(result);
            if(json.get("media_url") != null){
                logoUrl = json.getString("media_url");
            }
        }

        CashCouponBatch cashCouponBatch = new CashCouponBatch();
        cashCouponBatch.setStock_name(couponGrant.getStockName());
        cashCouponBatch.setBelong_merchant("1601420795");//漫狸商户号
        cashCouponBatch.setAvailable_begin_time(couponGrant.getAvailableBeginTime());
        cashCouponBatch.setAvailable_end_time(couponGrant.getAvailableEndTime());
        CashCouponBatchStockUseRule stockRule = new CashCouponBatchStockUseRule();
        stockRule.setMax_coupons(couponGrant.getMaxCoupons());
//        stockRule.setMax_amount(couponGrant.getMaxAmount());
        stockRule.setMax_amount(couponGrant.getMaxCoupons()*couponGrant.getCouponAmount());
        stockRule.setMax_amount_by_day(couponGrant.getMaxAmountByDay());
        stockRule.setMax_coupons_per_user(couponGrant.getMaxCouponsPerUser());
        stockRule.setNatural_person_limit(false);
        stockRule.setPrevent_api_abuse(true);
        cashCouponBatch.setStock_use_rule(stockRule);
        CashCouponBatchPatternInfo patternInfo = new CashCouponBatchPatternInfo();
        patternInfo.setDescription(couponGrant.getDescription());
        patternInfo.setMerchant_logo(logoUrl);
        patternInfo.setMerchant_name(branches.get(0).getBranchName());
        patternInfo.setBackground_color("COLOR020");
        patternInfo.setCoupon_image(logoUrl);
        cashCouponBatch.setPattern_info(patternInfo);
        CashCouponBatchCouponUseRule couponUseRule = new CashCouponBatchCouponUseRule();
        CashCouponBatchCouponUseRuleFixedNormalCoupon normalCoupon = new CashCouponBatchCouponUseRuleFixedNormalCoupon();
        normalCoupon.setCoupon_amount(couponGrant.getCouponAmount());
        normalCoupon.setTransaction_minimum(couponGrant.getTransactionMinimum());
        couponUseRule.setFixed_normal_coupon(normalCoupon);
        couponUseRule.setCombine_use(couponGrant.getCombineUse().intValue() == 1?true:false);
        List<String> list = new ArrayList<>();
        list.add(branches.get(0).getBranchId()+ "|" + "0" + "|" + "wechatgoodstag");//branchId|partnerId|wechatgoodstag,partnerId为空时填0
        couponUseRule.setGoods_tag(list);
        List<String> list1 = new ArrayList<>();
        list1.add(branches.get(0).getBranchWechatMchId());//子商户号
        couponUseRule.setAvailable_merchants(list1);
        cashCouponBatch.setCoupon_use_rule(couponUseRule);
        cashCouponBatch.setNo_cash(true);
        cashCouponBatch.setStock_type("NORMAL");
        cashCouponBatch.setOut_request_no(new Date().getTime() + "");
        String result1 = WxpayV3Utils.cashCouponBatch(cashCouponBatch,"1601420795");
        JSONObject jsonObject = JSONObject.parseObject(result1);
        if(jsonObject.get("stock_id") == null){
            throw new MyException(-1,jsonObject.toJSONString());
        }

        //商户自己激活优惠券批次是定时的，在timing项目,这里直插入
        WechatActivationCouponBatch wechatActivationCouponBatch = new WechatActivationCouponBatch();
        wechatActivationCouponBatch.setStockId(jsonObject.getString("stock_id"));
        wechatActivationCouponBatch.setWechatMchid(branches.get(0).getBranchWechatMchId());
        wechatActivationCouponBatch.setStatus(0);
        wechatActivationCouponBatch.setUpdateTime(new Date());
        wechatActivationCouponBatch.setStockName(couponGrant.getStockName());
        wechatActivationCouponBatch.setAvailableBeginTime(couponGrant.getAvailableBeginTime());
        wechatActivationCouponBatch.setAvailableEndTime(couponGrant.getAvailableEndTime());
        wechatActivationCouponBatch.setMaxCoupons(couponGrant.getMaxCoupons().intValue());
        wechatActivationCouponBatch.setMaxAmount(Integer.parseInt(String.valueOf(couponGrant.getMaxCoupons()*couponGrant.getCouponAmount())));
        wechatActivationCouponBatch.setMaxAmountByDay(couponGrant.getMaxAmountByDay().intValue());
        wechatActivationCouponBatch.setMaxCouponsPerUser(couponGrant.getMaxCouponsPerUser().intValue());
        wechatActivationCouponBatch.setDescription(couponGrant.getDescription());
        wechatActivationCouponBatch.setCouponAmount(couponGrant.getCouponAmount().intValue());
        wechatActivationCouponBatch.setTransactionMinimum(couponGrant.getTransactionMinimum().intValue());
        wechatActivationCouponBatch.setCombineUse(couponGrant.getCombineUse());
        wechatActivationCouponBatch.setStopStatus(1);
        wechatActivationCouponBatch.setUserGetNum(0);
        wechatActivationCouponBatchDao.insert(wechatActivationCouponBatch);
    }

    public void partnerCreateCouponBatch(CouponGrant couponGrant,Integer partnerId)throws Exception{
        //商户自己生成优惠券

        //优惠券logo获取
        List<Partner> partners = partnerDao.execute("select * from partner where partner_id = ?",partnerId);
        if(partners.size() == 0){
            return;
        }
        if(partners.get(0).getPartnerWechatMchId() == null){
            throw new MyException(-1,"商户未设置微信商户号");
        }
        if(couponGrant.getCombineUse() == null){
            throw new MyException(-1,"请选择是否可叠加使用");
        }
        String logoUrl = "";
        //使用漫狸的头像图片作为代金券logo
        Branch branch = branchDao.single(1);
        File file = HttpUtil.httpsGetImagAsFile(branch.getBranchHeadImg());
        String result = WxpayV3Utils.imgUpload(file,"1601420795");
        if(result != null){
            JSONObject json = JSONObject.parseObject(result);
            if(json.get("media_url") != null){
                logoUrl = json.getString("media_url");
            }
        }

        CashCouponBatch cashCouponBatch = new CashCouponBatch();
        cashCouponBatch.setStock_name(couponGrant.getStockName());
        cashCouponBatch.setBelong_merchant("1601420795");//漫狸商户号
        cashCouponBatch.setAvailable_begin_time(couponGrant.getAvailableBeginTime());
        cashCouponBatch.setAvailable_end_time(couponGrant.getAvailableEndTime());
        CashCouponBatchStockUseRule stockRule = new CashCouponBatchStockUseRule();
        stockRule.setMax_coupons(couponGrant.getMaxCoupons());
        //        stockRule.setMax_amount(couponGrant.getMaxAmount());
        stockRule.setMax_amount(couponGrant.getMaxCoupons()*couponGrant.getCouponAmount());
        stockRule.setMax_amount_by_day(couponGrant.getMaxAmountByDay());
        stockRule.setMax_coupons_per_user(couponGrant.getMaxCouponsPerUser());
        stockRule.setNatural_person_limit(false);
        stockRule.setPrevent_api_abuse(true);
        cashCouponBatch.setStock_use_rule(stockRule);
        CashCouponBatchPatternInfo patternInfo = new CashCouponBatchPatternInfo();
        patternInfo.setDescription(couponGrant.getDescription());
        patternInfo.setMerchant_logo(logoUrl);
        patternInfo.setMerchant_name(partners.get(0).getPartnerName());
        patternInfo.setBackground_color("COLOR020");
        patternInfo.setCoupon_image(logoUrl);
        cashCouponBatch.setPattern_info(patternInfo);
        CashCouponBatchCouponUseRule couponUseRule = new CashCouponBatchCouponUseRule();
        CashCouponBatchCouponUseRuleFixedNormalCoupon normalCoupon = new CashCouponBatchCouponUseRuleFixedNormalCoupon();
        normalCoupon.setCoupon_amount(couponGrant.getCouponAmount());
        normalCoupon.setTransaction_minimum(couponGrant.getTransactionMinimum());
        couponUseRule.setFixed_normal_coupon(normalCoupon);
        List<String> list = new ArrayList<>();
        list.add(partners.get(0).getBranchId()+ "|" + partners.get(0).getPartnerId() + "|" + "wechatgoodstag");//branchId|partnerId|wechatgoodstag,partnerId为空时填0
        couponUseRule.setGoods_tag(list);
        List<String> list1 = new ArrayList<>();
        list1.add(partners.get(0).getPartnerWechatMchId());//子商户号
        couponUseRule.setAvailable_merchants(list1);
        couponUseRule.setCombine_use(couponGrant.getCombineUse().intValue() == 1?true:false);
        cashCouponBatch.setCoupon_use_rule(couponUseRule);
        cashCouponBatch.setNo_cash(true);
        cashCouponBatch.setStock_type("NORMAL");
        cashCouponBatch.setOut_request_no(new Date().getTime() + "");
        String result1 = WxpayV3Utils.cashCouponBatch(cashCouponBatch,"1601420795");
        JSONObject jsonObject = JSONObject.parseObject(result1);
        if(jsonObject.get("stock_id") == null){
            throw new MyException(-1,jsonObject.toJSONString());
        }

        //商户自己激活优惠券批次是定时的，在timing项目,这里直插入
        WechatActivationCouponBatch wechatActivationCouponBatch = new WechatActivationCouponBatch();
        wechatActivationCouponBatch.setStockId(jsonObject.getString("stock_id"));
        wechatActivationCouponBatch.setWechatMchid(partners.get(0).getPartnerWechatMchId());
        wechatActivationCouponBatch.setStatus(0);
        wechatActivationCouponBatch.setUpdateTime(new Date());
        wechatActivationCouponBatch.setStockName(couponGrant.getStockName());
        wechatActivationCouponBatch.setAvailableBeginTime(couponGrant.getAvailableBeginTime());
        wechatActivationCouponBatch.setAvailableEndTime(couponGrant.getAvailableEndTime());
        wechatActivationCouponBatch.setMaxCoupons(couponGrant.getMaxCoupons().intValue());
        wechatActivationCouponBatch.setMaxAmount(Integer.parseInt(String.valueOf(couponGrant.getMaxCoupons()*couponGrant.getCouponAmount())));
        wechatActivationCouponBatch.setMaxAmountByDay(couponGrant.getMaxAmountByDay().intValue());
        wechatActivationCouponBatch.setMaxCouponsPerUser(couponGrant.getMaxCouponsPerUser().intValue());
        wechatActivationCouponBatch.setDescription(couponGrant.getDescription());
        wechatActivationCouponBatch.setCouponAmount(couponGrant.getCouponAmount().intValue());
        wechatActivationCouponBatch.setTransactionMinimum(couponGrant.getTransactionMinimum().intValue());
        wechatActivationCouponBatch.setCombineUse(couponGrant.getCombineUse());
        wechatActivationCouponBatch.setStopStatus(1);
        wechatActivationCouponBatch.setUserGetNum(0);
        wechatActivationCouponBatchDao.insert(wechatActivationCouponBatch);
    }

    public Result branchQueryCoupons1(QueryParamsCouponBatch queryParamsCouponBatch, HttpServletRequest request) throws Exception{
//        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
//        Integer branchId = sessionInfo.getBranchId();
//        Integer partnerId = sessionInfo.getPartnerId();
//        ObjectEmptyUtil.queryParamsCouponBatchIsEmpty(queryParamsCouponBatch);

        Integer branchId = 1;
        Integer partnerId = null;

        if(branchId != null && partnerId == null){
            if(branchId.intValue() == 1){
                StringBuffer sql = new StringBuffer("SELECT " +
                        " a.* ,b.bp_name " +
                        "FROM " +
                        " wechat_activation_coupon_batch a " +
                        " LEFT JOIN ( SELECT branch_name bp_name, branch_wechat_mch_id wechat_mchid FROM branch UNION ALL SELECT partner_name bp_name, partner_wechat_mch_id wechat_mchid FROM partner ) b on a.wechat_mchid = b.wechat_mchid " +
                        "WHERE " +
                        " 1 = 1 ");
                sql.append(queryParamsCouponBatch.getStatus() == null?"":" and a.status = " + queryParamsCouponBatch.getStatus());
                sql.append(queryParamsCouponBatch.getStopStatus() == null?"":" and a.stop_status = " + queryParamsCouponBatch.getStopStatus());
                sql.append(StringUtil.isEmpty(queryParamsCouponBatch.getStockName())?"":" and a.stock_name like '%" + queryParamsCouponBatch.getStockName() + "%'");
                sql.append(queryParamsCouponBatch.getTransactionMinimumMax() == null?"":" and a.transaction_minimum <= " + queryParamsCouponBatch.getTransactionMinimumMax());
                sql.append(queryParamsCouponBatch.getTransactionMinimumMin() == null?"":" and a.transaction_minimum >= " + queryParamsCouponBatch.getTransactionMinimumMin());

                SQLReady sqlReady = new SQLReady(sql.toString());

                PageQuery<WechatActivationCouponBatch> pageQuery = new PageQuery<WechatActivationCouponBatch>(queryParamsCouponBatch.getPage().longValue(),queryParamsCouponBatch.getLimit().longValue());
                PageQuery<WechatActivationCouponBatch> query =sqlManager.execute(sqlReady,WechatActivationCouponBatch.class,pageQuery);
                return ResultUtil.success(query.getList(),query.getTotalRow());
            }else{
                Branch branch = branchDao.single(branchId);
                StringBuffer sql = new StringBuffer("SELECT " +
                        " a.* ,b.bp_name " +
                        "FROM " +
                        " wechat_activation_coupon_batch a " +
                        " LEFT JOIN ( SELECT branch_name bp_name, branch_wechat_mch_id wechat_mchid FROM branch UNION ALL SELECT partner_name bp_name, partner_wechat_mch_id wechat_mchid FROM partner ) b on a.wechat_mchid = b.wechat_mchid " +
                        "WHERE " +
                        " 1 = 1 ");
                sql.append(queryParamsCouponBatch.getStatus() == null?"":" and a.status = " + queryParamsCouponBatch.getStatus());
                sql.append(queryParamsCouponBatch.getStopStatus() == null?"":" and a.stop_status = " + queryParamsCouponBatch.getStopStatus());
                sql.append(StringUtil.isEmpty(queryParamsCouponBatch.getStockName())?"":" and a.stock_name like '%" + queryParamsCouponBatch.getStockName() + "%'");
                sql.append(queryParamsCouponBatch.getTransactionMinimumMax() == null?"":" and a.transaction_minimum <= " + queryParamsCouponBatch.getTransactionMinimumMax());
                sql.append(queryParamsCouponBatch.getTransactionMinimumMin() == null?"":" and a.transaction_minimum >= " + queryParamsCouponBatch.getTransactionMinimumMin());
                SQLReady sqlReady = new SQLReady(sql.toString(),branch.getBranchWechatMchId());

                PageQuery<WechatActivationCouponBatch> pageQuery = new PageQuery<WechatActivationCouponBatch>(queryParamsCouponBatch.getPage().longValue(),queryParamsCouponBatch.getLimit().longValue());
                PageQuery<WechatActivationCouponBatch> query =sqlManager.execute(sqlReady,WechatActivationCouponBatch.class,pageQuery);
                return ResultUtil.success(query.getList(),query.getTotalRow());
            }


        }
        if(partnerId != null){
            Partner partner = partnerDao.single(partnerId);
            StringBuffer sql = new StringBuffer("SELECT " +
                    " a.* ,b.bp_name " +
                    "FROM " +
                    " wechat_activation_coupon_batch a " +
                    " LEFT JOIN ( SELECT branch_name bp_name, branch_wechat_mch_id wechat_mchid FROM branch UNION ALL SELECT partner_name bp_name, partner_wechat_mch_id wechat_mchid FROM partner ) b on a.wechat_mchid = b.wechat_mchid " +
                    "WHERE " +
                    " 1 = 1 ");
            sql.append(queryParamsCouponBatch.getStatus() == null?"":" and a.status = " + queryParamsCouponBatch.getStatus());
            sql.append(queryParamsCouponBatch.getStopStatus() == null?"":" and a.stop_status = " + queryParamsCouponBatch.getStopStatus());
            sql.append(StringUtil.isEmpty(queryParamsCouponBatch.getStockName())?"":" and a.stock_name like '%" + queryParamsCouponBatch.getStockName() + "%'");
            sql.append(queryParamsCouponBatch.getTransactionMinimumMax() == null?"":" and a.transaction_minimum <= " + queryParamsCouponBatch.getTransactionMinimumMax());
            sql.append(queryParamsCouponBatch.getTransactionMinimumMin() == null?"":" and a.transaction_minimum >= " + queryParamsCouponBatch.getTransactionMinimumMin());

            SQLReady sqlReady = new SQLReady(sql.toString(),partner.getPartnerWechatMchId());
            PageQuery<WechatActivationCouponBatch> pageQuery = new PageQuery<WechatActivationCouponBatch>(queryParamsCouponBatch.getPage().longValue(),queryParamsCouponBatch.getLimit().longValue());
            PageQuery<WechatActivationCouponBatch> query =sqlManager.execute(sqlReady,WechatActivationCouponBatch.class,pageQuery);
            return ResultUtil.success(query.getList(),query.getTotalRow());
        }

        return ResultUtil.success();
    }

    public Result branchQueryCoupons(QueryParamsCouponBatch queryParamsCouponBatch, HttpServletRequest request) throws Exception{
//        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
//        Integer branchId = sessionInfo.getBranchId();
//        Integer partnerId = sessionInfo.getPartnerId();
//        ObjectEmptyUtil.queryParamsCouponBatchIsEmpty(queryParamsCouponBatch);

        Integer branchId = 20;
        Integer partnerId = null;

        JSONArray array = new JSONArray();
        if(branchId != null && partnerId == null){
            QueryCouponStockStatus stockStatus = new QueryCouponStockStatus();
            stockStatus.setOffset(queryParamsCouponBatch.getPage());
            stockStatus.setLimit(queryParamsCouponBatch.getLimit());
            stockStatus.setStock_creator_mchid("1601420795");
            JSONObject jsonObject = JSONObject.parseObject(WxpayV3Utils.queryCouponStockStatus(stockStatus,"1601420795"));

            Branch branch = branchDao.single(branchId);
            if(jsonObject.get("data") != null){
                array = jsonObject.getJSONArray("data");
                array.removeIf(object -> {
                    JSONObject couponInfp = (JSONObject)object;
                    List<WechatActivationCouponBatch> batches = wechatActivationCouponBatchDao.execute("select * from wechat_activation_coupon_batch where stock_id = ?",couponInfp.getString("stock_id"));
                    if(batches.size() > 0 && batches.get(0).getWechatMchid().equals(branch.getBranchWechatMchId())){
                        return false;
                    }else{
                        return true;
                    }
                });

            }
        }
        if(partnerId != null){
            QueryCouponStockStatus stockStatus = new QueryCouponStockStatus();
            stockStatus.setOffset(queryParamsCouponBatch.getPage());
            stockStatus.setLimit(queryParamsCouponBatch.getLimit());
            stockStatus.setStock_creator_mchid("1601420795");
            JSONObject jsonObject = JSONObject.parseObject(WxpayV3Utils.queryCouponStockStatus(stockStatus,"1601420795"));

            Partner partner = partnerDao.single(partnerId);
            if(jsonObject.get("data") != null){
                array = jsonObject.getJSONArray("data");
                array.removeIf(object -> {
                    JSONObject couponInfp = (JSONObject)object;
                    List<WechatActivationCouponBatch> batches = wechatActivationCouponBatchDao.execute("select * from wechat_activation_coupon_batch where stock_id = ?",couponInfp.getString("stock_id"));
                    if(batches.size() > 0 && batches.get(0).getWechatMchid().equals(partner.getPartnerWechatMchId())){
                        return false;
                    }else{
                        return true;
                    }
                });

            }
        }

        return ResultUtil.success(array);
    }

    @Transactional
    public Result branchStopCoupons(CouponGrantStop couponGrantStop, HttpServletRequest request) throws Exception{
        if(couponGrantStop.getStockId() == null){
            return ResultUtil.error(-1,"优惠券批次号为空");
        }
        if(couponGrantStop.getStopOrStart() == null){
            return ResultUtil.error(-1,"开启或停止状态为空");
        }
        if(couponGrantStop.getStopOrStart().intValue() == 1){
            //开启优惠券
            StopCoupon stopCoupon = new StopCoupon();
            stopCoupon.setStock_creator_mchid("1601420795");
            String result1 = WxpayV3Utils.restartCoupon(stopCoupon,couponGrantStop.getStockId(),"1601420795");
            JSONObject jsonObject = JSONObject.parseObject(result1);
            if(jsonObject.get("stock_id") == null){
                throw new MyException(-1,jsonObject.toJSONString());
            }else{
                wechatActivationCouponBatchDao.executeUpdate("update wechat_activation_coupon_batch set stop_status = 1 where stock_id = ?",couponGrantStop.getStockId());
            }
        }else{
            //停止优惠券
            StopCoupon stopCoupon = new StopCoupon();
            stopCoupon.setStock_creator_mchid("1601420795");
            String result1 = WxpayV3Utils.stopCoupon(stopCoupon,couponGrantStop.getStockId(),"1601420795");
            JSONObject jsonObject = JSONObject.parseObject(result1);
            if(jsonObject.get("stock_id") == null){
                throw new MyException(-1,jsonObject.toJSONString());
            }else{
                wechatActivationCouponBatchDao.executeUpdate("update wechat_activation_coupon_batch set stop_status = 0 where stock_id = ?",couponGrantStop.getStockId());
            }
        }
        return ResultUtil.success();
    }

    public Result goodsClass(HttpServletRequest request)throws Exception {
        TaobaoGoodsClassQuery taobaoGoodsClassQuery = new TaobaoGoodsClassQuery();
        taobaoGoodsClassQuery.setApikey(dingdanxiaKey);
        taobaoGoodsClassQuery.setTree("true");
        JSONArray data = dingDanXiaUtils.taobaokeGoodsClass(taobaoGoodsClassQuery);
        data.forEach(object -> {
            JSONObject json = (JSONObject) object;
            if(json.get("child") != null){
                json.remove("child");
            }
        });
        return ResultUtil.success(data.size()> 21?data.subList(0,20):data);
    }

    public Result getCouponListByClass(TaobaoGoodsClassQueryCouponList t) throws Exception{
        TaobaoGoodsCouponListQuery taobaoGoodsClassQuery = new TaobaoGoodsCouponListQuery();
        taobaoGoodsClassQuery.setApikey(dingdanxiaKey);
        taobaoGoodsClassQuery.setMin_id(t.getMinId());
        if("数码家电".equals(t.getKeyword())){
            taobaoGoodsClassQuery.setKeyword("数码");
        }else if("文娱车品".equals(t.getKeyword())){
            taobaoGoodsClassQuery.setKeyword("车品");
        }else{
            taobaoGoodsClassQuery.setKeyword(t.getKeyword());
        }
        JSONObject result = dingDanXiaUtils.taobaokeGoodsCouponList(taobaoGoodsClassQuery);

        Long midid = Long.parseLong(t.getMinId()) + 1;
        if(result == null){
            return ResultUtil.success(new ArrayList(),midid);
        }else{
            JSONArray data = result.getJSONArray("data");
            if(result.get("min_id") != null){
                midid = result.getLong("min_id");
            }
            return ResultUtil.success(data,midid);
        }
    }

    public Result getCouponTklByGoodsId(TaobaoGoodsClassQueryCouponTkl t) throws Exception{
        TaobaoGoodsToTklByGoodsIdQuery taobaoGoodsClassQuery = new TaobaoGoodsToTklByGoodsIdQuery();
        taobaoGoodsClassQuery.setApikey(dingdanxiaKey);
        taobaoGoodsClassQuery.setActivityId(t.getActivityId());
        taobaoGoodsClassQuery.setId(t.getItemId());
        taobaoGoodsClassQuery.setPid("mm_1077940154_1491900319_110220800463");
        taobaoGoodsClassQuery.setTpwd("true");
        JSONObject data = dingDanXiaUtils.taobaokeGoodsToTklById(taobaoGoodsClassQuery);

        return ResultUtil.success(data);
    }

    public Result getCouponInfoByGoodsId(TaobaoGoodsClassQueryCouponInfo t) throws Exception {
        TaobaoGoodsCouponListQuery taobaoGoodsClassQuery = new TaobaoGoodsCouponListQuery();
        taobaoGoodsClassQuery.setApikey(dingdanxiaKey);
        taobaoGoodsClassQuery.setMin_id("1");
        taobaoGoodsClassQuery.setKeyword(t.getItemId());
        JSONObject data = dingDanXiaUtils.taobaokeGoodsCouponInfo(taobaoGoodsClassQuery);

        return ResultUtil.success(data);
    }

    public Result getCouponClass1() {
        List<MajorType> majorTypes = majorTypeDao.execute("select * from major_type where status = 1");
        return ResultUtil.success(majorTypes);
    }

    public Result getCouponListByClass1(ManTaoTaoCouponsByClass t) {
        ObjectEmptyUtil.getCouponListByClass1IsEmpty(t);
        String sql = " " +
                "select * from ( " +
                "SELECT " +
                " a.*,b.branch_head_img head_img,b.branch_name shop_name,b.branch_id as branch_id,null as partner_id,b.longitude,b.latitude,if(a.user_get_num is not null,round(a.user_get_num/a.max_coupons*100,0),100) coupon_got " +
                "FROM " +
                " wechat_activation_coupon_batch a " +
                " LEFT JOIN (select f.* from (select * from major_branch_partner where major_type_id = ? and partner_id is null) e left join branch f on e.branch_id = f.branch_id ) b ON a.wechat_mchid = b.branch_wechat_mch_id  " +
                "WHERE " +
                " a.user_get_num < a.max_coupons  and b.branch_head_img is not null and a.status = 1 " +
                "union all  " +
                "SELECT " +
                " a.*,b.partner_head_img head_img,b.partner_name shop_name,null as branch_id,b.partner_id,b.longitude,b.latitude,if(a.user_get_num is not null,round(a.user_get_num/a.max_coupons*100,0),100) coupon_got " +
                "FROM " +
                " wechat_activation_coupon_batch a " +
                " LEFT JOIN (select f.* from (select * from major_branch_partner where major_type_id = ? and partner_id is not null) e left join partner f on e.partner_id = f.partner_id ) b ON a.wechat_mchid = b.partner_wechat_mch_id " +
                "WHERE " +
                " a.user_get_num < a.max_coupons  and b.partner_head_img is not null and a.status = 1 " +
                ") d where d.shop_name is not null  and REPLACE ( SUBSTRING( d.available_begin_time FROM 1 FOR 19 ), 'T', ' ' ) <= now() and REPLACE ( SUBSTRING( d.available_end_time FROM 1 FOR 19 ), 'T', ' ' ) > now() ";
        SQLReady sqlReady = new SQLReady(sql,t.getMajorTypeId(),t.getMajorTypeId());
        PageQuery<Map> pageQuery = new PageQuery<Map>(t.getPage().longValue(),t.getLimit().longValue());
        PageQuery<Map> executePageQuery = sqlManager.execute(sqlReady, Map.class,pageQuery);
        List<Map> list = executePageQuery.getList();
        if(list.size() > 0 ){
            if(t.getLongitude() == null){
                //没传经纬度，不进行距离排序
                return ResultUtil.success(list,pageQuery.getTotalRow());
            }else{
                //传了经纬度，进行距离排序
                LocationPoint p1 = new LocationPoint(t.getLongitude(),t.getLatitude());
                list.stream().forEach(map -> {
                    if(map.get("longitude") == null || map.get("latitude") == null){
                        map.put("distance",9999999.9);
                    }else{
                        LocationPoint p2 = new LocationPoint(Double.parseDouble(map.get("longitude").toString()) ,Double.parseDouble(map.get("latitude").toString()));
                        map.put("distance",LocationUtils.getDistance(p1,p2));
                    }
                });
                List<Map> sortedList = list.stream().sorted(Comparator.comparing(map -> {
                    return (Double)map.get("distance");
                })).collect(Collectors.toList());

                return ResultUtil.success(sortedList,pageQuery.getTotalRow());
            }
        }
        return ResultUtil.success(new ArrayList());
    }

    public Result getCouponListBySearch(ManTaoTaoCouponsByKeyWord t) {
        ObjectEmptyUtil.getCouponListByKeyWord1IsEmpty(t);
        String sql = "select * from ( " +
                "SELECT " +
                " a.*,b.branch_head_img head_img,b.branch_name shop_name,b.longitude,b.latitude,if(a.user_get_num is not null,round(a.user_get_num/a.max_coupons*100,0),100) coupon_got " +
                "FROM " +
                " wechat_activation_coupon_batch a " +
                " LEFT JOIN (select * from branch where branch_name like '%" + (StringUtils.isEmpty(t.getKeyWord())?"":t.getKeyWord())+"%') b ON a.wechat_mchid = b.branch_wechat_mch_id  " +
                "WHERE " +
                " a.user_get_num < a.max_coupons " +
                "union all  " +
                "SELECT " +
                " a.*,b.partner_head_img head_img,b.partner_name shop_name,b.longitude,b.latitude,if(a.user_get_num is not null,round(a.user_get_num/a.max_coupons*100,0),100) coupon_got " +
                "FROM " +
                " wechat_activation_coupon_batch a " +
                " LEFT JOIN (select * from partner where partner_name like '%" + (StringUtils.isEmpty(t.getKeyWord())?"":t.getKeyWord())+"%') b ON a.wechat_mchid = b.partner_wechat_mch_id " +
                "WHERE " +
                " a.user_get_num < a.max_coupons " +
                ") d where d.shop_name is not null  and REPLACE ( SUBSTRING( d.available_begin_time FROM 1 FOR 19 ), 'T', ' ' ) <= now() and REPLACE ( SUBSTRING( d.available_end_time FROM 1 FOR 19 ), 'T', ' ' ) > now() ";
        SQLReady sqlReady = new SQLReady(sql);
        PageQuery<Map> pageQuery = new PageQuery<Map>(t.getPage().longValue(),t.getLimit().longValue());
        PageQuery<Map> executePageQuery = sqlManager.execute(sqlReady, Map.class,pageQuery);
        List<Map> list = executePageQuery.getList();
        if(list.size() > 0 ){
            if(t.getLongitude() == null){
                //没传经纬度，不进行距离排序
                return ResultUtil.success(list,pageQuery.getTotalRow());
            }else{
                //传了经纬度，进行距离排序
                LocationPoint p1 = new LocationPoint(t.getLongitude(),t.getLatitude());
                list.stream().forEach(map -> {
                    if(map.get("longitude") == null || map.get("latitude") == null){
                        map.put("distance",9999999.9);
                    }else{
                        LocationPoint p2 = new LocationPoint(Double.parseDouble(map.get("longitude").toString()) ,Double.parseDouble(map.get("latitude").toString()));
                        map.put("distance",LocationUtils.getDistance(p1,p2));
                    }
                });
                List<Map> sortedList = list.stream().sorted(Comparator.comparing(map -> {
                    return (Double)map.get("distance");
                })).collect(Collectors.toList());

                return ResultUtil.success(sortedList,pageQuery.getTotalRow());
            }
        }
        return ResultUtil.success(new ArrayList());
    }

    @Transactional
    public Result getCoupon(ManTaoTaoCouponsGet t, HttpServletRequest request) throws Exception{
        if(StringUtils.isEmpty(t.getStockId())){
            ResultUtil.error(-1,"代金券stocid缺失");
        }
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        String unionid = sessionInfo.getWeChatUserInfo().getUnionid();
//        String unionid = "o0tFauGmtAyDVeL26O6NF0Huzcr0";
        List<WeChatUserInfo> list = weChatUserInfoDao.execute("select * from we_chat_user_info where source = 1 and unionid = ?",unionid);
        if(list.size() > 0){
            //redis加锁,抢锁等待时间比较重要，过期时间不重要
            String identifier =  redisUtil.lockWithTimeout("lingquyhq" + t.getStockId(),6000,10000);

            List<WechatUserGetCouponLog> list1 = wechatUserGetCouponLogDao.execute("select * from wechat_user_get_coupon_log where stock_id = ? and openid = ?",t.getStockId(),list.get(0).getOpenid());
            if(list1.size() > 0){
                ResultUtil.error(-1,"您已经领取过了！");
            }
            //向微信请求领取
            GrantCoupon grantCoupon = new GrantCoupon();
            grantCoupon.setStock_id(t.getStockId());
            String reNo = new Date().getTime() + unionid;
            grantCoupon.setOut_request_no(reNo);
            grantCoupon.setAppid(appID);
            grantCoupon.setStock_creator_mchid("1601420795");
            JSONObject json =  JSONObject.parseObject(WxpayV3Utils.grantCoupon(grantCoupon,list.get(0).getOpenid(),"1601420795"));
            if(json.get("coupon_id") == null){
                throw new MyException(-1,"领取失败！" + (json.get("message") == null?"":json.getString("message")));
            }
            //领取完毕后插入数据库
            WechatUserGetCouponLog wechatUserGetCouponLog = new WechatUserGetCouponLog();
            wechatUserGetCouponLog.setCouponId(json.getString("coupon_id"));
            wechatUserGetCouponLog.setOpenid(list.get(0).getOpenid());
            wechatUserGetCouponLog.setRequestNo(reNo);
            wechatUserGetCouponLog.setStockCreatorMchid("1601420795");
            wechatUserGetCouponLog.setWxAppId(appID);
            wechatUserGetCouponLog.setStockId(t.getStockId());
            wechatUserGetCouponLog.setInsertTime(new Date());
            wechatUserGetCouponLogDao.insert(wechatUserGetCouponLog);

            //领取数量加一
            List<WechatActivationCouponBatch> list2 = wechatActivationCouponBatchDao.execute("select * from wechat_activation_coupon_batch where stock_id = ? limit 1",t.getStockId());
            if(list2.size() > 0){
                Integer nnum = list2.get(0).getUserGetNum() + 1;
                wechatActivationCouponBatchDao.executeUpdate("update wechat_activation_coupon_batch set user_get_num = ? where stock_id = ?",nnum,t.getStockId());
            }
            //redis解锁
            redisUtil.lockDel("lingquyhq" + t.getStockId(),identifier);
            return ResultUtil.success();
        }else{
            return ResultUtil.error(-1,"请先关注漫淘淘公众号吧！");
        }
    }

    public Result myCouponsList(QueryParamsMyCoupons t, HttpServletRequest request) throws Exception{
        if(t.getPage() == null){
            ResultUtil.error(-1,"分页参数缺失");
        }
        SessionInfo sessionInfo = sessionInfoUtils.getSessionInfoByAuth(request);
        String unionid = sessionInfo.getWeChatUserInfo().getUnionid();
//        String unionid = "o0tFauD-Mv_bta2Gs6mvQlvsCPlU";
//        String unionid = "o0tFauGmtAyDVeL26O6NF0Huzcr0";
        List<WeChatUserInfo> list = weChatUserInfoDao.execute("select * from we_chat_user_info where source = 1 and unionid = ?",unionid);
        Long totalRow = null;
        if(list.size() > 0){
            //根据商户号查用户的券
            QueryCouponByMerchant queryCouponByMerchant = new QueryCouponByMerchant();
            queryCouponByMerchant.setOffset(t.getPage());
            queryCouponByMerchant.setLimit(t.getLimit());
            queryCouponByMerchant.setAppid(appID);
//            queryCouponByMerchant.setStatus("SENDED");
            queryCouponByMerchant.setCreator_mchid("1601420795");
            JSONObject json =  JSONObject.parseObject(WxpayV3Utils.queryCouponByMerchant(queryCouponByMerchant,list.get(0).getOpenid(),"1601420795"));
            if(json.get("total_count") == null){
                throw new MyException(-1,"查询失败，请稍候重试！");
            }
            totalRow = json.getLong("total_count");
            JSONArray array = json.getJSONArray("data");
            JSONArray result = new JSONArray();
            array.forEach(object -> {
                JSONObject jsonObject = (JSONObject)object;
                String sql = "SELECT " +
                        " b.branch_id, " +
                        " b.partner_id, " +
                        " b.head_img, " +
                        " b.shop_name  " +
                        "FROM " +
                        " wechat_activation_coupon_batch a " +
                        " LEFT JOIN ( SELECT branch_id,null as partner_id,branch_head_img head_img, branch_name shop_name, branch_wechat_mch_id wechat_mchid FROM branch UNION ALL SELECT null as branch_id,partner_id,partner_head_img head_img, partner_name shop_name, partner_wechat_mch_id wechat_mchid FROM partner ) b ON a.wechat_mchid = b.wechat_mchid  " +
                        "WHERE " +
                        " a.stock_id = ?";
                SQLReady sqlReady = new SQLReady(sql,jsonObject.getString("stock_id"));
                List<Map> list1 = sqlManager.execute(sqlReady,Map.class);
                if(list1.size() > 0){
                    jsonObject.put("head_img",list1.get(0).get("headImg").toString());
                    jsonObject.put("shop_name",list1.get(0).get("shopName").toString());
                    if(list1.get(0).get("branchId") != null){
                        jsonObject.put("branch_id",list1.get(0).get("branchId").toString());
                    }
                    if(list1.get(0).get("partnerId") != null){
                        jsonObject.put("partner_id",list1.get(0).get("partnerId").toString());
                    }
                }
                result.add(jsonObject);
            });
            return ResultUtil.success(result,totalRow);
        }else{
            return ResultUtil.error(-1,"请先关注漫淘淘公众号吧！");
        }
    }
}
